package com.arcsoft.arcfacedemo.activity;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.Toast;

import com.arcsoft.arcfacedemo.R;
import com.arcsoft.arcfacedemo.common.Constants;
import com.arcsoft.arcfacedemo.model.DrawInfo;
import com.arcsoft.arcfacedemo.util.DrawHelper;
import com.arcsoft.arcfacedemo.util.LogPlus;
import com.arcsoft.arcfacedemo.util.camera.CameraHelper;
import com.arcsoft.arcfacedemo.util.camera.CameraListener;
import com.arcsoft.arcfacedemo.widget.FaceRectView;
import com.arcsoft.face.ActiveFileInfo;
import com.arcsoft.face.AgeInfo;
import com.arcsoft.face.ErrorInfo;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.GenderInfo;
import com.arcsoft.face.VersionInfo;

import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;


/**
 * 视频检测实时离线人脸识别
 */
public class PreviewActivity extends AppCompatActivity implements ViewTreeObserver.OnGlobalLayoutListener {
    private static final String       TAG         = "PreviewActivity";
    private              CameraHelper cameraHelper;
    private              DrawHelper   drawHelper;
    private              Camera.Size  previewSize;
    private              Integer      rgbCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    private              FaceEngine   faceEngine;
    private              int          afCode      = -1;
    private              Toast        toast       = null;
    private              int          processMask = FaceEngine.ASF_AGE
            | FaceEngine.ASF_FACE3DANGLE
            | FaceEngine.ASF_GENDER
            //| FaceEngine.ASF_LIVENESS
            ;//初始化人脸识别

    private int          initMask = FaceEngine.ASF_FACE_DETECT
            | FaceEngine.ASF_AGE
            | FaceEngine.ASF_FACE3DANGLE
            | FaceEngine.ASF_GENDER
            //| FaceEngine.ASF_LIVENESS
            ;//初始化引擎
    /**
     * 相机预览显示的控件，可为SurfaceView或TextureView
     */
    private View         previewView;
    private FaceRectView faceRectView;

    private static final int      ACTION_REQUEST_PERMISSIONS = 0x001;
    /**
     * 所需的所有权限信息
     */
    private static final String[] NEEDED_PERMISSIONS         = new String[]{
            Manifest.permission.CAMERA,
            Manifest.permission.READ_PHONE_STATE
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_preview);


        //        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//全屏
        //
        //        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        //            WindowManager.LayoutParams attributes = getWindow().getAttributes();
        //            attributes.systemUiVisibility = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        //            getWindow().setAttributes(attributes);
        //        }
        //
        //        // Activity启动后就锁定为启动时的方向
        //        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
        //


        previewView = findViewById(R.id.texture_preview);//摄像头预览插件

        faceRectView = findViewById(R.id.face_rect_view);//人脸识别框框
        //在布局结束后才做初始化操作
        previewView.getViewTreeObserver().addOnGlobalLayoutListener(PreviewActivity.this);


    }

    private void initEngine() {
        faceEngine = new FaceEngine();

        //初始化人脸引擎
        LogPlus.e("------> 初始化人脸引擎" + initMask + ",人脸识别角度:" + 2);

        afCode = faceEngine.init(this, FaceEngine.ASF_DETECT_MODE_VIDEO,
                2,//获取本地存储的识别角度
                16, 20,
                initMask
        );
        //	ASF_FACE_DETECT
        //初始化和调用引擎的属性，人脸检测
        //	ASF_AGE
        //初始化和调用引擎的属性，年龄检测
        //	ASF_FACE3DANGLE
        //初始化和调用引擎的属性，人脸三维角度检测
        //ASF_GENDER
        //初始化和调用引擎的属性，性别检测

        //	ASF_IR_LIVENESS
        //初始化和调用引擎的属性，IR活体检测

        VersionInfo versionInfo = new VersionInfo();//版本信息类
        faceEngine.getVersion(versionInfo);
        LogPlus.e(TAG, "当前识别引擎的版本initEngine:  init: " + afCode + "  version:" + versionInfo);
        if (afCode != ErrorInfo.MOK) {
            Toast.makeText(this, getString(R.string.init_failed, afCode), Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 销毁人脸识别引擎
     */
    private void unInitEngine() {

        if (afCode == 0) {
            afCode = faceEngine.unInit();
            LogPlus.e(TAG, "销毁人脸识别引擎 unInitEngine: " + afCode);
        }
    }


    @Override
    protected void onDestroy() {
        if (cameraHelper != null) {
            cameraHelper.release();
            cameraHelper = null;
        }
        unInitEngine();
        super.onDestroy();
    }

    private boolean checkPermissions(String[] neededPermissions) {
        if (neededPermissions == null || neededPermissions.length == 0) {
            return true;
        }
        boolean allGranted = true;
        for (String neededPermission : neededPermissions) {
            allGranted &= ContextCompat.checkSelfPermission(this.getApplicationContext(), neededPermission) == PackageManager.PERMISSION_GRANTED;
        }
        return allGranted;
    }

    private void initCamera() {

        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

        CameraListener cameraListener = new CameraListener() {
            @Override
            public void onCameraOpened(Camera camera, int cameraId, int displayOrientation, boolean isMirror) {

                LogPlus.e(TAG, "打开摄像头onCameraOpened:cameraId: " + cameraId
                        + " displayOrientation: " + displayOrientation
                        + "是都镜像isMirror " + isMirror);

                previewSize = camera.getParameters().getPreviewSize();

                //回话人脸框
                drawHelper = new DrawHelper(previewSize.width,
                        previewSize.height,
                        previewView.getWidth(),
                        previewView.getHeight(),
                        displayOrientation,
                        cameraId,
                        isMirror,
                        true,
                        false);
            }


            @Override
            public void onPreview(byte[] nv21, Camera camera) {
                //LogPlus.e("------> 预览回调!");

                if (faceRectView != null) {
                    faceRectView.clearFaceInfo();
                }

                List<FaceInfo> faceInfoList = new ArrayList<>();//接收人脸数量

                //人脸检测
                //参数:
                //data - 输入的图像数据
                //width - 图像的宽度，为4的倍数
                //height - 图像的高度，NV21(CP_PAF_NV21)格式为2的倍数；BGR24(CP_PAF_BGR24)、
                // GRAY(CP_PAF_GRAY)、DEPTH_U16(CP_PAF_DEPTH_U16)格式无限制
                //format - 图像的颜色空间格式，支持NV21(CP_PAF_NV21)、BGR24(CP_PAF_BGR24)、
                // GRAY(CP_PAF_GRAY)、DEPTH_U16(CP_PAF_DEPTH_U16)
                //faceInfoList - 人脸列表，传入后赋值
                int code = faceEngine.detectFaces(nv21, previewSize.width, previewSize.height,
                        FaceEngine.CP_PAF_NV21, faceInfoList);

                if (code == ErrorInfo.MOK && faceInfoList.size() > 0) {

                    //process   RGB活体、年龄、性别、三维角度检测，在调用该函数后，
                    // 可以调用getLiveness(List) ，getAge(List)，getGender(List)，
                    // getFace3DAngle(List)分别获取 RGB活体、年龄、性别、三维角度的检测结果；
                    // RGB活体最多支持 1 个人脸信息的检测，超过部分返回未知；
                    // 年龄、性别、三维角度最多支持4个人脸信息的检测，超过部分返回未知
                    code = faceEngine.process(nv21, previewSize.width, previewSize.height,
                            FaceEngine.CP_PAF_NV21, faceInfoList, processMask);
                    if (code != ErrorInfo.MOK) {
                        LogPlus.e("------>code!=0  RGB活体、年龄、性别、三维角度检测");
                        return;
                    }
                } else {
                    //有可能人脸检测失败 或者没有检测到人脸
                    // LogPlus.e("------>code!=0 人脸检测 有可能人脸检测失败 或者没有检测到人脸");
                    return;
                }

                List<AgeInfo> ageInfoList = new ArrayList<>();
                List<GenderInfo> genderInfoList = new ArrayList<>();
                //List<Face3DAngle> face3DAngleList = new ArrayList<>();
                // List<LivenessInfo> faceLivenessInfoList = new ArrayList<>();
                int ageCode = faceEngine.getAge(ageInfoList);
                int genderCode = faceEngine.getGender(genderInfoList);
                //int face3DAngleCode = faceEngine.getFace3DAngle(face3DAngleList);
                //int livenessCode = faceEngine.getLiveness(faceLivenessInfoList);

                //有其中一个的错误码不为0，return
                if ((ageCode | genderCode// | face3DAngleCode //| livenessCode
                ) != ErrorInfo.MOK) {
                    LogPlus.e("------> 有其中一个的错误码不为0，return ");

                    return;
                }
                if (faceRectView != null && drawHelper != null) {
                    List<DrawInfo> drawInfoList = new ArrayList<>();
                    for (int i = 0; i < faceInfoList.size(); i++) {


                        drawInfoList.add(new DrawInfo(drawHelper.adjustRect(faceInfoList.get(i).getRect()),
                                genderInfoList.get(i).getGender(),
                                ageInfoList.get(i).getAge(),
                                0, null)
                        );


                        LogPlus.e("------> 识别结果:性别:"
                                + (genderInfoList.get(i).getGender() ==
                                GenderInfo.MALE ? "男" : (genderInfoList.get(i).getGender() ==
                                GenderInfo.FEMALE ? "女" : "未知"))

                                + ",  年龄:" + ageInfoList.get(i).getAge()
                        );
                    }
                    drawHelper.draw(faceRectView, drawInfoList);
                }
            }

            @Override
            public void onCameraClosed() {
                Log.i(TAG, "onCameraClosed: ");
            }

            @Override
            public void onCameraError(Exception e) {
                Log.i(TAG, "onCameraError: " + e.getMessage());
            }

            @Override
            public void onCameraConfigurationChanged(int cameraID, int displayOrientation) {
                if (drawHelper != null) {
                    drawHelper.setCameraDisplayOrientation(displayOrientation);
                }
                Log.i(TAG, "onCameraConfigurationChanged: " + cameraID + "  " + displayOrientation);
            }
        };

        cameraHelper = new CameraHelper.Builder()
                .previewViewSize(new Point(previewView.getMeasuredWidth(), previewView.getMeasuredHeight()))
                .rotation(getWindowManager().getDefaultDisplay().getRotation())
                .specificCameraId(rgbCameraId != null ? rgbCameraId : Camera.CameraInfo.CAMERA_FACING_FRONT)
                .isMirror(false)//是否镜像
                //.additionalRotation(90)//额外的旋转角度（用于适配一些定制设备）
                .previewOn(previewView)
                .cameraListener(cameraListener)
                .build();

        cameraHelper.init();
        cameraHelper.start();


    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == ACTION_REQUEST_PERMISSIONS) {
            boolean isAllGranted = true;
            for (int grantResult : grantResults) {
                isAllGranted &= (grantResult == PackageManager.PERMISSION_GRANTED);
            }
            if (isAllGranted) {
                initEngine();
                initCamera();
                if (cameraHelper != null) {
                    cameraHelper.start();
                }
            } else {
                Toast.makeText(this.getApplicationContext(), R.string.permission_denied, Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * 在{@link #previewView}第一次布局完成后，去除该监听，并且进行引擎和相机的初始化
     */
    @Override
    public void onGlobalLayout() {
        LogPlus.e("------> 第一次布局完成后，去除该监听，并且进行引擎和相机的初始化");
        previewView.getViewTreeObserver().removeOnGlobalLayoutListener(this);//移除监听




        FaceEngine faceEngineInit = new FaceEngine();
        Observable.create(
                new Observable.OnSubscribe<Integer>() {
                    @Override
                    public void call(Subscriber<? super Integer> subscriber) {
                        //在线激活人脸识别引擎

                        int activeCode = faceEngineInit.activeOnline(PreviewActivity.this, Constants.APP_ID, Constants.SDK_KEY);
                        subscriber.onNext(activeCode);
                        subscriber.onCompleted();
                        LogPlus.e("------>activeCode: " + activeCode);
                    }
                }
        ).subscribeOn(Schedulers.io())
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Integer>() {
                               @Override
                               public void onCompleted() {

                               }

                               @Override
                               public void onError(Throwable e) {

                               }

                               @Override
                               public void onNext(Integer activeCode) {
                                   LogPlus.e("------> 接收到的返回值:" + activeCode);

                                   runOnUiThread(new Runnable() {
                                       @Override
                                       public void run() {
                                           if (activeCode == ErrorInfo.MOK) {

                                               showToast("激活引擎成功");
                                               //startActivity(new Intent(PreviewActivity.this, PreviewActivity.class));

                                               intitAll();

                                           } else if (activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED) {
                                               showToast("引擎已激活，无需再次激活");
                                               //startActivity(new Intent(PreviewActivity.this, PreviewActivity.class));
                                               intitAll();

                                           } else {
                                               Log.d(TAG, "onNext: 引擎激活失败，错误码为 " + activeCode);
                                               showToast(getString(R.string.active_failed, activeCode));
                                               // TODO: 2019/7/3 这里要上报 !
                                           }


                                           ActiveFileInfo activeFileInfo = new ActiveFileInfo();
                                           //激活文件信息类
                                           int res = faceEngineInit.getActiveFileInfo(PreviewActivity.this, activeFileInfo);
                                           if (res == ErrorInfo.MOK) {
                                               Log.e(TAG, "激活文件信息类:" + activeFileInfo.toString());
                                           }

                                       }
                                   });

                               }
                           }
                );


        //        Observable.create(new ObservableOnSubscribe<Integer>() {
        //            @Override
        //            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
        //
        //                //在线激活人脸识别引擎
        //                int activeCode = faceEngineInit.activeOnline(PreviewActivity.this, Constants.APP_ID, Constants.SDK_KEY);
        //                emitter.onNext(activeCode);
        //            }
        //        })
        //                .subscribeOn(Schedulers.io())
        //                .observeOn(AndroidSchedulers.mainThread())
        //                .subscribe(new Observer<Integer>() {
        //                    @Override
        //                    public void onSubscribe(Disposable d) {
        //
        //                    }
        //
        //                    @Override
        //                    public void onNext(Integer activeCode) {
        //                        if (activeCode == ErrorInfo.MOK) {
        //                            showToast("激活引擎成功");
        //                            //startActivity(new Intent(PreviewActivity.this, PreviewActivity.class));
        //
        //                            intitAll();
        //
        //                        } else if (activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED) {
        //                            showToast("引擎已激活，无需再次激活");
        //                            //startActivity(new Intent(PreviewActivity.this, PreviewActivity.class));
        //                            intitAll();
        //
        //                        } else {
        //                            Log.d(TAG, "onNext: 引擎激活失败，错误码为 " + activeCode);
        //                            showToast(getString(R.string.active_failed, activeCode));
        //                            // TODO: 2019/7/3 这里要上报 !
        //                        }
        //
        //
        //                        ActiveFileInfo activeFileInfo = new ActiveFileInfo();
        //                        //激活文件信息类
        //                        int res = faceEngineInit.getActiveFileInfo(PreviewActivity.this, activeFileInfo);
        //                        if (res == ErrorInfo.MOK) {
        //                            Log.e(TAG, "激活文件信息类:" + activeFileInfo.toString());
        //                        }
        //                    }
        //
        //                    @Override
        //                    public void onError(Throwable e) {
        //
        //                    }
        //
        //                    @Override
        //                    public void onComplete() {
        //
        //                    }
        //                });


    }

    /**
     * 初始化引擎和摄像头
     */
    public void intitAll() {
        //检查权限
        if (!checkPermissions(NEEDED_PERMISSIONS)) {
            ActivityCompat.requestPermissions(PreviewActivity.this, NEEDED_PERMISSIONS, ACTION_REQUEST_PERMISSIONS);
        } else {
            initEngine();//初始引擎
            initCamera();//初始化摄像头
        }
    }

    private void showToast(String s) {
        if (toast == null) {
            toast = Toast.makeText(this, s, Toast.LENGTH_SHORT);
            toast.show();
        } else {
            toast.setText(s);
            toast.show();
        }
    }
}
